class Controller {

  int count_l4 = 0;              
  int count_l3 = 0;              
  int count_l2 = 0;              
  int count_l1 = 0;              
  int id = 0;
  ArrayList<Field> field;
  boolean turn;
  Brain br=new Brain(21);
  ArrayList<Ship> Ships = new ArrayList<Ship>();

  Ship ship;


  //РљРѕРЅСЃС‚СЂСѓРєС‚РѕСЂ РєР»Р°СЃСЃР°
  Controller(ArrayList<Field> fd, boolean s) {
    this.field = fd;
    this.turn = s;
    this.ship=null;
  }
  public ArrayList<Ship> getShips() {
    return this.Ships;
  }
  public void syncField(TPoint p) {
      Field f1=getField(1);
      Field f2=getField(0);
      f1.setCellValue(p.getY(), p.getX(), f2.getCellValue(p.getY(), p.getX()));
      for(int i = 0; i< f1.getCount();i++){
        for(int j = 0; j< f1.getCount();j++)
          if (f2.getCellValue(i, j) == -2 ){
            f1.setCellValue(i, j, -2);
          } else if (f2.getCellValue(i, j) == 11){
            f1.setCellValue(i, j, 11);
          }
      }
  }
  public ArrayList<Field> getField() { 
    return this.field;
  }
  public void setField(ArrayList<Field> fd) {
    this.field=fd;
  }
  public Field getField(int i) {
    return field.get(i);
  }
  public void setField(int i, Field fd) {
    if (this.field.size()<i) {
      field.add(fd);
    } 
    else {
      field.set(i, fd);
    }
  }
  private boolean isInjured(){
    for(int i=0;i<getField(0).getCount();i++){
      for(int j=0;j<getField(0).getCount();j++){
        
        if (getField(0).getCellValue(j,i) == 12 ){
          return true;
        }
      }
    }
    return false;
 }
 public boolean win(){

    for (int i=0;i< Ships.size();i++) {

      if (!Ships.get(i).isDie()) {
        return false;
      }
    }

    return true;
   
 }
  public TPoint getShoot() {
    return br.shoot(getField(0), getMaxLengthLiveShip(),isInjured());
  }
  public void setTurn(boolean b) {
    this.turn = b;
  }
  public boolean isTurn() {
    return this.turn;
  }

  public void makeShoot(TPoint p, boolean auto) {
    
    if (auto) {
      p = cell(p, getField(0));
    } 
    int value = getField(1).getCellValue(p.getY(), p.getX());
 
    if (value > 0 && value <11) {
       (Ships.get(value-1)).setState(Ships.get(value-1).getDeck(p), false);
     if (Ships.get(value-1).isDie()) {
          br.getBrush().setField(getField(0));
          br.getBrush().paintSegment(getShips().get(value-1).getDeck(getShips().get(value-1).getSize()-1), getShips().get(value-1).getDeck(0));
        for (int i=0;i<getShips().get(value-1).getSize();i++) {
          TPoint p1=getShips().get(value-1).getDeck(i); 
          getField(0).setCellValue(p1.getX(), p1.getY(), 11);
        }
        this.turn=true;
      } 
       else {
         getField(0).setCellValue(p.getY(), p.getX(), 12);
         this.turn=true;
       }
    }
     else {
     getField(0).setCellValue(p.getY(), p.getX(), -2);
     this.turn=false;
//      //println(getField(0).getCellValue(p.getY(), p.getX()));
    }
  }
  public void stat(Field fd) {

    if (count_l1 == 4 && count_l2 == 3 && count_l3 == 2 && count_l4 == 1) {
      rec(fd);
      clear(fd);
    }
  }

  public void clear(Field field) {
    count_l4 = 0;              //РљРѕР»РёС‡РµСЃС‚РІРѕ С‡РµС‚С‹СЂС‘С…РїР°Р»СѓР±РЅС‹С… РєРѕСЂР°Р±Р»РµР№ РЅР° РїРѕР»Рµ
    count_l3 = 0;              //РљРѕР»РёС‡РµСЃС‚РІРѕ С‚СЂС‘С…РїР°Р»СѓР±РЅС‹С… РєРѕСЂР°Р±Р»РµР№ РЅР° РїРѕР»Рµ
    count_l2 = 0;              //РљРѕР»РёС‡РµСЃС‚РІРѕ РґРІСѓС…РїР°Р»СѓР±РЅС‹С… РєРѕСЂР°Р±Р»РµР№ РЅР° РїРѕР»Рµ
    count_l1 = 0; 
    for (int i = 0; i <field.getCount(); i++) {
      for (int j = 0; j < field.getCount(); j++) {   
        field.setCellValue(i, j, 0);                 //Р—Р°РїРѕР»РЅРµРЅРёРµ РІСЃРµС… РєР»РµС‚РѕРє РЅСѓР»СЏРјРё
      }
    }
    id = 0;
  }

  public TPoint cell(TPoint point1, Field field) {
    if (point1.getX() < field.getCorn().getX() || point1.getY() < field.getCorn().getY() || point1.getX() >= field.getCorn().getX() + field.getCount() * field.getCellSize() || point1.getY() >= field.getCorn().getY()+field.getCount() * field.getCellSize()) {
      return new TPoint(-1, -1);
    }
    else {
      return  new TPoint(ceil((point1.getY() - field.getCorn().getY())/field.getCellSize()), ceil((point1.getX() - field.getCorn().getX())/field.getCellSize()));
    }
  }

  public void createShip(TPoint start1, TPoint stop1, boolean check, Field field) {
    int dx;                                    //Р”Р»РёРЅРЅР° РІС‹РґРµР»РµРЅРЅРѕР№ РѕР±Р»Р°СЃС‚Рё РїРѕ РіРѕСЂРёР·РѕРЅС‚Р°Р»Рё РІ РєР»РµС‚РєР°С…
    int dy;     //Р”Р»РёРЅРЅР° РІС‹РґРµР»РµРЅРЅРѕР№ РѕР±Р»Р°СЃС‚Рё РїРѕ РІРµСЂС‚РёРєР°Р»Рё РІ РєР»РµС‚РєР°С…
    TPoint start = new TPoint(0, 0);                              //РљРѕРѕСЂРґРёРЅР°С‚Р° РїРµСЂРІРѕР№ С‚РѕС‡РєРё РІС‹Р±РѕСЂР° РІ РєР»РµС‚РєР°С…
    TPoint stop = new TPoint(0, 0);                                //РљРѕРѕСЂРґРёРЅР°С‚Р° РїРѕСЃР»РµРґРЅРµР№ С‚РѕС‡РєРё РІС‹Р±РѕСЂР° РІ РєР»РµС‚РєР°С…
    boolean isempty = true;                    //Р’РѕР·РјРѕР¶РЅРѕСЃС‚СЊ СѓСЃС‚Р°РЅРѕРІРёС‚СЊ РІ РєР»РµС‚РєСѓ РєРѕСЂР°Р±Р»СЊ
    int len = 0;                               //РљРѕР»РёС‡РµСЃС‚РІРѕ РїР°Р»СѓР± РґРѕР±Р°РІР»СЏРµРјРѕРіРѕ РєРѕСЂР°Р±Р»СЏ
    boolean rules = false;                      //РљРѕР»РёС‡РµСЃС‚РІРѕ РєРѕСЂР°Р±Р»РµР№ РЅР° РїРѕР»Рµ РЅРµ РїСЂРµРІС‹С€Р°РµС‚ РґРѕРїСѓСЃС‚РёРјРѕРµ РєРѕР»РёС‡РµСЃС‚РІРѕ 

    start = start1; 
    stop = stop1;
    br.getBrush().setField(field);

    if (!check) { 
      start = cell(start1, field); 
      stop = cell(stop1, field);   
      //РџСЂРѕРІРµСЂРєР° РЅР° РїРѕРїР°РґР°РЅРёРµ РЅР°С‡Р°Р»СЊРЅРѕР№ Рё РєРѕРЅРµС‡РЅРѕР№ С‚РѕС‡РєРё РІС‹Р±РѕСЂР° РІ РїРѕР»Рµ
      if (start.getX() != -2 && stop.getX() != -2) {

        if (start.getY() == stop.getY() || start.getX() == stop.getX()) {  //Р›РµР¶Р°С‚ Р»Рё РІС‹СЂР°РЅРЅС‹Рµ С‚РѕС‡РєРё РЅР° РѕРґРЅРѕРј РѕС‚СЂРµР·РєРµ
          dx = abs(start.getY() - stop.getY());
          dy = abs(start.getX() - stop.getX());    

          //РџСЂРѕРІРµСЂРєР° РЅР° С‚Рѕ, С‡С‚РѕР±С‹ РєРѕР»РёС‡РµСЃС‚РІРѕ РїР°Р»СѓР± Р±С‹Р»Рѕ РЅРµ Р±РѕР»РµРµ 4-С…  
          if (dx < 4 && dy < 4) {
            if (dx != 0) {
              len = dx;
            } 
            else {
              len = dy;
            }

            rules = false;

            if (checkEmpty(start, stop, field)) {

              switch(len + 1) {
              case 1: 
                if (count_l1 < 4) {
                  rules = true;
                  count_l1 = count_l1 + 1;
                }  
                break;
              case 2: 
                if (count_l2 < 3) {
                  rules = true;
                  count_l2 = count_l2 + 1;
                }  
                break;
              case 3:
                if (count_l3 < 2) {
                  rules = true;
                  count_l3 = count_l3 + 1;
                }      
                break;
              case 4:
                if (count_l4 < 1) {
                  rules = true;
                  count_l4 = count_l4 + 1;
                }  
                break;
              }
              if (rules) {
                check = true;
              }
            }
          }
        }
      }
    }

    if (check) {
      id = id + 1; 
      int k = 0;
      ship = new Ship(id);
      for (int i = min(stop.getY(), start.getY()); i <=  max(stop.getY(), start.getY()); i++) {
        for (int j = min(stop.getX(), start.getX()); j <=  max(stop.getX(), start.getX()); j++) {
          field.setCellValue(i, j, id);
          ship.setState(k, true);
          k++;
          ship.addDeck(new TPoint(i, j));
          br.getBrush().paintSegment(i, j);
        }
      }
      Ships.add(ship);
    }
  }

  private boolean checkEmpty(TPoint start, TPoint stop, Field field) {

    boolean isempty = true;


    for (int i = min(stop.getY(), start.getY()); i <=  max(stop.getY(), start.getY()); i++) {
      for (int j = min(stop.getX(), start.getX()); j <=  max(stop.getX(), start.getX()); j++) {
        if (field.getCellValue(i, j) != 0) {
          isempty = false;
        }
      }
    }
    return isempty;
  }
  
  public void generation(Field fd) {    
    int c;
    ArrayList var;
    TLine line1;
    clear(fd);
    for (int i = 1 ; i < 5 ; i++) {
      for (int j = 1 ; j < 6 - i ; j++) {
        var = gen(i, fd);

        c = ceil(random(var.size()));
        line1 = (TLine) var.get(c - 1);
        createShip(line1.getp1(), line1.getp2(), true, fd);
      }
    }

    count_l1 = 4;
    count_l2 = 3;
    count_l3 = 2;
    count_l4 = 1;

    rec(fd);
  }
  
  public void genHard(Field fd){
    int c;
    ArrayList var;
    TLine line1;
    clear(fd);
    for (int i = 4 ; i > 1  ; i--) {
      for (int j = 1 ; j < 6 - i ; j++) {
        var = genNight(i, fd);
        c = ceil(random(var.size()));
        line1 = (TLine) var.get(c - 1);
        createShip(line1.getp1(), line1.getp2(), true, fd);
      }
    }
    
    for (int i = 0; i < 4; i++){
      var = gen(1, fd);
      c = ceil(random(var.size()));
      line1 = (TLine) var.get(c - 1);
      createShip(line1.getp1(), line1.getp2(), true, fd);  
    }

    count_l1 = 4;
    count_l2 = 3;
    count_l3 = 2;
    count_l4 = 1;
    
    rec(fd);

  }


  public ArrayList genNight(int c, Field field) {

    ArrayList result = new ArrayList();
    TLine line1;
    c = c - 1;

    for (int i = 0 ; i < 10 ; i++) {
      for (int j = 0 ; j < field.getCount()- c ; j++) {
        if (checkEmpty(new TPoint(i, j), new TPoint(i, j + c), field)) {
          if(i == 0 || i == 9){
            result.add(new TLine(i, j, i, j + c));
          }
        }
      }
    }

    for (int j = 0 ; j < 10 ; j++) {
      for (int i = 0 ; i < field.getCount() - c ; i++) {
        if (checkEmpty(new TPoint(i, j), new TPoint(i + c, j), field)) {
          if(j == 0 || j == 9){
            result.add(new TLine(i, j, i +c, j));
          }
        }
      }
    }

    return result;
  }
  
  
  public ArrayList gen(int c, Field field) {

    ArrayList result = new ArrayList();
    TLine line1;
    c = c - 1;

    for (int i = 0 ; i < 10 ; i++) {
      for (int j = 0 ; j < field.getCount()- c ; j++) {
        if (checkEmpty(new TPoint(i, j), new TPoint(i, j + c), field)) {
          result.add(new TLine(i, j, i, j + c));
        }
      }
    }

    for (int j = 0 ; j < 10 ; j++) {
      for (int i = 0 ; i < field.getCount() - c ; i++) {
        if (checkEmpty(new TPoint(i, j), new TPoint(i + c, j), field)) {
          result.add(new TLine(i, j, i +c, j));
        }
      }
    }

    return result;
  } 
  public int getMaxLengthLiveShip() {
    int m=0;

    for (int i=0;i< Ships.size();i++) {

      if (!Ships.get(i).isDie()) {
        if (m<Ships.get(i).getSize()) {
          m=Ships.get(i).getSize();
        }
      }
    }

    return m;
  }
  public void rec(Field field) {
    Statistics stat = new Statistics(field.getCells());
    stat.calc();
    stat.getVer(0, 0);
  }
} 

